// 一些战斗要用的功能
const mongoose = require('mongoose');
const User = require('../../../models/User/User');
const UserEquipment = require('../../../models/User/User_equipment');
const User_skill = require('../../../models/User/User_skill');
const Maps = require('../../../models/Map');
const Npc = require('../../../models/Npc/Npc');
const Monster = require('../../../models/Npc/Monster');

// 思路：
// 1.先判断玩家是否可以战斗
// 2.判断双方是否可以进行战斗（是否在同一区域）
// 3.判断对手是否可以进行战斗
// 4.战斗
// 5.返回战报

async function battle_check(uid, target_type, target_id) {
    // 3个参数：玩家id,玩家战斗的目标类型,目标id
    // 定义几个状态flag 用于返回给外面api
    // 0:正常 1:玩家状态不对 2:玩家和目标不在同一个地图 3：目标的状态不对
    console.log("battle_check");
    let flag = 0;
    if (target_type == 'player') {
        // 查看玩家的状态
        let check_user = await User.findOne({ _id: uid });
        if (check_user.status == 0) {
            // 玩家状态允许
            let check_player = await User.findOne({ _id: target_id });
            if (check_player.status == 0) {
                // 目标状态允许
                if (check_player.now_map == check_user.now_map) {
                    // 在同一地图

                    // 获取对应id的战斗数据
                    let arry_user_bs = await battle_bs_get(target_type, uid);
                    let arry_target_bs = await battle_bs_get(target_type, target_id);
                    let battle_result = await battle_main(arry_user_bs, arry_target_bs);
                    console.log("玩家bs", arry_user_bs);
                    console.log("目标Bs", arry_target_bs);
                    console.log("battle_main结果", battle_result);
                    // 应该要记录日志的，先留个位置

                    // 血量替换
                    let user_new_hp = battle_result[1];
                    let target_new_hp = battle_result[2];
                    let Updatemsg = { $set: { hp: user_new_hp } };
                    await User.findOneAndUpdate({ _id: uid }, Updatemsg, function (error) {
                        if (error) console.log("战斗更新血量报错");
                    }).then(user => {
                        console.log("攻击方",user.name,"血量更新", user.hp);
                    });;
                    Updatemsg = { $set: { hp: target_new_hp } };
                    await User.findOneAndUpdate({ _id: target_id }, Updatemsg, function (error) {
                        if (error) console.log("战斗更新血量报错");
                    }).then(user => {
                        console.log("防守方",user.name,"血量更新", user.hp);
                    });
                    return battle_result[0];
                } else {
                    flag = 2;
                    return flag
                }
            } else {
                flag = 3;
                return flag
            }
        } else {
            flag = 1;
            return flag
        }
    }
    else if (target_type == 'npc') {
        await battle_bs_get(target_type, target_id);
    }
    else if (target_type == 'monster') {

    }
}
async function battle_bs_get(target_type, id) {
    let bs_strength = 0;
    let bs_defense = 0;
    let bs_magic = 0;
    let bs_speed = 0;
    let bs_user_exp = 0;
    let user_hp = 0;
    let eq_strength = 0;
    let eq_defense = 0;
    let eq_magic = 0;
    let eq_speed = 0;
    let bs_arry = [];
    if (target_type == 'player') {
        let player = await User.findOne({ _id: id });
        let equipment = await UserEquipment.find({ user: id, status: '1' });
        if (equipment.length <= 0) {
            bs_strength = player.strength;
            bs_defense = player.defense;
            bs_magic = player.magic;
            bs_speed = player.speed;
            user_hp = player.hp;
        } else {
            for (let i = 0; i < equipment.length; i++) {
                eq_strength += equipment[i].strength;
                eq_defense += equipment[i].defense;
                eq_magic += equipment[i].magic;
                eq_speed += equipment[i].speed;
            };
            bs_strength = player.strength + eq_strength;
            bs_defense = player.defense + eq_defense;
            bs_magic = player.magic + eq_magic;
            bs_speed = player.speed + eq_speed;
            bs_user_exp = player.user_exp;
            user_hp = player.hp;
        }
        bs_arry.push(bs_strength, bs_defense, bs_magic, bs_speed, bs_user_exp, user_hp);
        return bs_arry;
    }
    else if (target_type == 'npc') {
        let player = await Npc.findOne({ uid: id });
        // ----------------暂时没做NPC的装备------------------------//
        // let equipment = await UserEquipment.find({ user: id,status: '1' });
        // console.log("穿戴中的bs",equipment);
        // if(equipment.length <= 0){
        //     bs_strength = player.strength;
        //     bs_defense = player.defense;
        //     bs_magic = player.magic;
        //     bs_speed = player.speed;
        // }else{
        //     for(let i=0; i<equipment.length; i++){
        //         eq_strength += equipment.length[i].strength;
        //         eq_defense += equipment.length[i].defense;
        //         eq_magic += equipment.length[i].magic;
        //         eq_speed += equipment.length[i].speed;
        //     };
        // bs_strength = player.strength + eq_strength;
        // bs_defense = player.defense + eq_defense;
        // bs_magic = player.magic + eq_magic;
        // bs_speed = player.speed + eq_speed;
        // bs_user_exp = player.user_exp;
        //}
        bs_strength = player.strength;
        bs_defense = player.defense;
        bs_magic = player.magic;
        bs_speed = player.speed;
        bs_user_exp = player.user_exp;
        user_hp = player.hp;
        bs_arry.push(bs_strength, bs_defense, bs_magic, bs_speed, bs_user_exp, user_hp);
        return bs_arry;
    }
    else if (target_type == 'monster') {
        console("野怪方法");
    }
}
async function battle_main(user_arry, target_arry) {
    // 获取的数据定义
    let bs_user_strength = user_arry[0];
    let bs_user_defense = user_arry[1];
    let bs_user_magic = user_arry[2];
    let bs_user_speed = user_arry[3];
    let bs_user_exp = user_arry[4];
    let bs_user_hp = user_arry[5];
    let bs_target_strength = target_arry[0];
    let bs_target_defense = target_arry[1];
    let bs_target_magic = target_arry[2];
    let bs_target_speed = target_arry[3];
    let bs_target_exp = user_arry[4];
    let bs_target_hp = user_arry[5];

    // 战斗相关数据定义
    let battle_exp_buff = 0; // 境界差别buff
    if (bs_user_exp == 0) { // 别问，避免0exp打0exp的情况
        bs_user_exp = 1;
    }
    if (bs_target_exp == 0) {// 别问，避免0exp打0exp的情况
        bs_target_exp = 1;
    }
    let battle_exp_compare = bs_user_exp / bs_target_exp; // 境界差别计算
    let speed_arry = [];// 用于接收速度相关的数组
    let battle_result = [];// 用于接收结果的数组
    if (battle_exp_compare <= 0.01) {
        console.log("case 1");
        user_exp_buff = 0.01;
        tar_exp_buff = 1;
        speed_arry = await speed_compare(bs_user_speed, bs_target_speed);
        if (speed_arry[0] == 0) {
            // 主动攻击方先手
            // 说明攻击方命中率高
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 攻击方是主动方
            battle_result = await v1_battle_func(bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff, bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff);
        } else {
            // 防守方先手
            // 说明攻击方命中率低
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 反手方是主动方
            battle_result = await v1_battle_func(bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff, bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff);
        }
    } else if (battle_exp_compare < 0.5) {
        console.log("case 2");
        user_exp_buff = 0.5;
        target_exp_buff = 1;
        speed_arry = await speed_compare(bs_user_speed, bs_target_speed);
        if (speed_arry[0] == 0) {
            // 主动攻击方先手
            // 说明攻击方命中率高
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 攻击方是主动方
            battle_result = await v1_battle_func(bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff, bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff);
        } else {
            // 防守方先手
            // 说明攻击方命中率低
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 反手方是主动方
            battle_result = await v1_battle_func(bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff, bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff);
        }
    } else if (battle_exp_compare >= 1) {
        console.log("case 3");
        user_exp_buff = 1;
        target_exp_buff = 1;
        speed_arry = await speed_compare(bs_user_speed, bs_target_speed);
        if (speed_arry[0] == 0) {
            // 主动攻击方先手
            // 说明攻击方命中率高
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 攻击方是主动方
            battle_result = await v1_battle_func(bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff, bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff);
        } else {
            // 防守方先手
            // 说明攻击方命中率低
            let user_accuracy = speed_arry[1];
            let target_accuracy = speed_arry[2];
            // 反手方是主动方
            battle_result = await v1_battle_func(bs_target_hp, bs_target_strength, bs_target_defense, bs_target_magic, target_accuracy, target_exp_buff, bs_user_hp, bs_user_strength, bs_user_defense, bs_user_magic, user_accuracy, user_exp_buff);
        }
    }
    // 输出双方血量和战斗结果
    console.log("battle_result", battle_result);
    console.log("战斗结果", battle_result[0]);
    console.log("进攻方:", battle_result[1]);
    console.log("防守方:", battle_result[2]);
    return battle_result;
}


async function speed_compare(user_val, target_val) {
    // 战力速度差计算
    // 返回一个数组 [出手顺序,攻击方命中率,防守方命中率] 
    // 出手顺序：0 user出手 1 target出手
    // 命中率：用速度相除计算标准值，大于0 必中，小于0取小数点后4位，得到的数值最大说明速度越接近，命中率较高。相反就小。
    // 命中率计算
    let standard = user_val / target_val; //计算标准值
    let first_attck;
    let return_arry = [];
    let target_standard;
    let user_standard
    if (standard >= 1) {
        first_attck = 0;
        target_standard = standard.toFixed(4);
        user_standard = 1;
    } else {
        first_attck = 1;
        user_standard = standard.toFixed(4);
        let target_standard = 1;
    };
    return_arry.push(first_attck, user_standard, target_standard);
    return return_arry;
}

async function accuracy(user_val, target_val) {
    // （备用一个）装备命中率计算方法
}

async function v1_atk_func(total_atk, target_defense, accuracy, exp_buff) {
    // 单次攻击方计算方法 version 1
    // 需要参数：total_atk、magic、命中率
    // 输出单次攻击的伤害
    // 整合strength和magic
    let damage = Math.floor(total_atk * exp_buff) - target_defense;
    // 命中率拿到的要么是1，要么是小于1的数。random 0-1 的数判断即可
    // 
    if (accuracy == 1) {
        // 命中率100%的时候
    } else if (Math.random().toFixed(4) <= accuracy) {
        // 命中率小于100%的时候，Math.random()是0-1的大区间，由于命中率不够，说明会无法命中，所以说明命中率是做小区间，命中率越低，区间越小，随机到的概率越低。
    } else {
        // 未命中
        damage = 0;
    }
    if(damage <= 0){damage=0};
    return damage;
}

async function v1_hpdown_func(damage, hp) {
    // 受击扣血方法 version 1
    // 输入参数：伤害，受击方的生命值
    // 输出：Arry [是否结束战斗(0：未 1：结束),剩余生命值]
    let return_Arry = [];
    let flag = 0;
    let after_hp = Math.floor(hp - damage);
    if (after_hp <= 0) {
        flag = 1;
        after_hp = 0;
        return_Arry.push(flag, after_hp);
        return return_Arry;
    } else {
        return_Arry.push(flag, after_hp);
        return return_Arry;
    };
}

async function v1_battle_func(user_hp, user_strength, user_defense, user_magic, user_accuracy, user_exp_buff, target_hp, target_strength, target_defense, target_magic, target_accuracy, target_exp_buff) {
    // 第一版战斗方法
    // 物理攻击和法术攻击同行计算，暂不区分物理和法术的关系
    // 暂不使用技能进行战斗
    // 暂不计算武器命中率
    // 需要输入玩家和目标对应的strength、defense、magic、命中率、境界差别buff、hp
    // 输出数组 [胜利结果,攻击方Hp,防守hp]
    let user_total_atk = user_strength + user_magic;
    let target_total_atk = target_strength + target_magic;
    let Arry_hp = [];
    let result = 0; //胜利结果 0：攻击方胜 1：防守方胜
    let hp_result;
    while (user_hp > 0 || target_hp > 0) {
        damage = await v1_atk_func(user_total_atk, target_defense, user_accuracy, user_exp_buff);
        console.log("先手damage",damage);
        hp_result = await v1_hpdown_func(damage, user_hp);
        user_hp = hp_result[1];
        if (user_hp[0] == 1) break;
        damage = await v1_atk_func(target_total_atk, user_defense, target_accuracy, target_exp_buff);
        console.log("后手damage",damage);
        hp_result = await v1_hpdown_func(damage, user_hp);
        target_hp = hp_result[1];
        if (hp_result[0] == 1) break;
    }
    if (user_hp > 0 && target_hp <= 0) {
        result = 1;
    } else {
        result = 0;
    }
    Arry_hp.push(result, user_hp, target_hp);
    return Arry_hp;
}



module.exports = {
    battle_check: battle_check,
};